package com.zycfc.zsf.boot.logback.util;

import java.util.concurrent.atomic.*;
import java.util.concurrent.*;

public class MiscUtil
{
    private static final char[] CHARS;
    private static final char[] SPECIAL_CHARS;
    private static final int RADIX = 36;
    private static final int LIMIT;
    private static final LongAdder ADDER;
    private static final long MAX_VALUE = 9223372036854765807L;
    
    public static String getRandomStr(final int destLen, final boolean whitSpecialChars) {
        final StringBuilder sb = new StringBuilder();
        int range = MiscUtil.CHARS.length;
        if (whitSpecialChars) {
            range += MiscUtil.SPECIAL_CHARS.length;
        }
        for (int i = 0; i < destLen; ++i) {
            final int rand = ThreadLocalRandom.current().nextInt(range);
            if (rand < MiscUtil.CHARS.length) {
                sb.append(MiscUtil.CHARS[rand]);
            }
            else {
                sb.append(MiscUtil.SPECIAL_CHARS[rand - MiscUtil.CHARS.length]);
            }
        }
        return sb.toString();
    }
    
    public static String genUniqueStr() {
        final StringBuilder sb = new StringBuilder();
        MiscUtil.ADDER.increment();
        long serialNum = MiscUtil.ADDER.longValue();
        if (serialNum >= 9223372036854765807L) {
            synchronized (MiscUtil.ADDER) {
                if (MiscUtil.ADDER.longValue() >= 9223372036854765807L) {
                    MiscUtil.ADDER.reset();
                }
            }
        }
        serialNum %= MiscUtil.LIMIT;
        if (serialNum > MiscUtil.LIMIT) {
            throw new RuntimeException("serialNum \u8d85\u8fc7\uff1a" + MiscUtil.LIMIT);
        }
        final int m = (int)(serialNum / MiscUtil.CHARS.length);
        final int n = (int)(serialNum % MiscUtil.CHARS.length);
        sb.append(MiscUtil.CHARS[m]);
        sb.append(MiscUtil.CHARS[n]);
        sb.append(Long.toString(System.currentTimeMillis(), 36));
        sb.append(Integer.toString(ThreadLocalRandom.current().nextInt(36), 36));
        sb.append(Integer.toString(ThreadLocalRandom.current().nextInt(36), 36));
        return sb.toString();
    }
    
    static {
        CHARS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
        SPECIAL_CHARS = new char[] { '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '+', '=', '{', '}', '[', ']', '|', '\\', ';', ':', '\"', '<', '.', '>', '/', '?' };
        LIMIT = MiscUtil.CHARS.length * MiscUtil.CHARS.length - 1;
        ADDER = new LongAdder();
    }
}
